<?php
namespace zake\foundation\point;

use zake\foundation\able\ProtocolAble;
use zake\foundation\able\reactor\ConnectAble;
use zake\foundation\able\stream\ReadBufferAble;


/**
 * Class Table
 * @package zake\foundation\point
 *
 *
 */
class Table implements ProtocolAble
{

    // 首次连接成功，可以基于sessionID和timestamp成功一个public key传给client
    // 服务端 encode(session id , body) -> hash code

    //    255    +    255    +    255    +    255    +
    // ---- ---- + ---- ---- + ---- ---- + ---- ---- +
    //                   action code                 | 4 byte (增查改删)(C.R.U.D)
    // ---- ---- + ---- ---- + ---- ---- + ---- ---- +
    //                     id code                   | 4 byte（数据key）（新增可以为0，也可以指定下标，如果有重复，则覆盖）
    // ---- ---- + ---- ---- + ---- ---- + ---- ---- +
    //                  name length                  | 4 byte (表名)
    // ---- ---- + ---- ---- + ---- ---- + ---- ---- +
    //                  body length                  | 4 byte (内容)
    // ---- ---- + ---- ---- + ---- ---- + ---- ---- +
    //                  name                         | 表名
    // ---- ---- + ---- ---- + ---- ---- + ---- ---- +
    //                  body                         | 数据内容（增才有）
    // ---- ---- + ---- ---- + ---- ---- + ---- ---- |


    // action code
    const ACTION_INSERT   = 0X01000000;  // 增
    const ACTION_DELETE   = 0X00010000;  // 删
    const ACTION_MODIFY   = 0X00000100;  // 改
    const ACTION_SELECT   = 0X00000001;  // 查

    // action code map
    const ACTION_MAP = [
        'C'=>self::ACTION_INSERT,
        'R'=>self::ACTION_SELECT,
        'U'=>self::ACTION_MODIFY,
        'D'=>self::ACTION_DELETE,
    ];


    /**
     * @var Table | null | ProtocolAble
     */
    private static $singleton = null;


    /**
     * 构造器
     *
     * @author liu.bin 2020-04-03 23:16
     */
    public static function singleton()
    {
        if(is_null(static::$singleton)){
            static::$singleton = new static();
        }
        return static::$singleton;
    }


    /**
     * 计算frameLength
     *
     * @param string $buffer
     * @param ReadBufferAble $connect
     *
     * @return int|false
     *          int - 数据包长度（0-没有获取到长度）
     *          false - 数据包错误，需要关闭当前链接
     * @author liu.bin 2020-05-19 16:29
     */
    public function framePoint($buffer,ReadBufferAble $connect)
    {



    }



    /**
     * 解包 格式化输出数据包的内容
     *
     * @param string|array $struct
     * @return string|array
     */
    public function decode($buffer, ConnectAble $stream = null)
    {

        $actionCode = substr($buffer,0,3);
        $id         = substr($buffer,4,4);
        $nameLength = substr($buffer,8,4);
        $bodyLength = substr($buffer,12,4);

        $name = substr($buffer,16,$nameLength);
        $body = substr($buffer,16+$nameLength);
        return "";
    }



    /**
     * 数据打包
     *
     * 比如http协议，buffer只为http的body部分，此处需要添加http的header部分
     *
     * @param string $buffer
     * @return string
     */
    public function encode($buffer, ConnectAble $stream = null)
    {
        list($action,$id,$name,$body) = $this->decodeBuffer($buffer);
        $nameLen = strlen($name);
        $bodyLen = strlen($body);
        $buffer = pack('N',$action) . pack('N',$id) . pack('N',$nameLen) . $name.pack("N",$bodyLen).$body;
        return $buffer;
    }



    /**
     * buffer 解码
     * @param  $buffer
     * @return array
     * @author liu.bin 2020-05-12 13:32
     */
    private function decodeBuffer($buffer)
    {
        list($action,$id,$name,$body) = json_decode($buffer,true);
        $action = is_string($action) ? (self::ACTION_MAP[$action]??0) : $action;
        return [$action,$id,$name,$body];
        //return json_encode($body,JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    }
}


